<template>
  <div class="form-container">
    <div class="form-wrapper">
      <Form
        ref="expForm"
        :model="expForm"
        :rules="ruleValidate"
        :label-position="labelPosition"
        :label-width="labelWidth">
          <fieldset class="line-field" ref="baseInfoRef">
            <legend>{{ fieldsetTitle }}</legend>
            <FormItem label="基本信息" class="ivu-form-item-required">
              <Row :gutter="20" type="flex" justify="space-around">
                <Col span="2" class="pl-15">编号：</Col>
                <Col span="5">
                  <FormItem>
                    <Input disabled placeholder="实验编号" :value="expIndex"></Input>
                  </FormItem>
                </Col>
                <Col span="2" class="pl-15">类型：</Col>
                <Col span="6">
                  <FormItem prop="type">
                    <Select :enabledPreventOverflow="enabledPreventOverflow" clearable filterable v-model="expForm.type" placeholder="实验类型">
                      <Option value="验证性">验证性</Option>
                      <Option value="演示性">演示性</Option>
                      <Option value="练习性">练习性</Option>
                      <Option value="创新性">创新性</Option>
                      <Option value="设计性">设计性</Option>
                      <Option value="综合性">综合性</Option>
                      <Option value="其他">其他</Option>
                    </Select>
                  </FormItem>
                </Col>
                <Col span="2" class="pl-15">学时：</Col>
                <Col span="6">
                  <FormItem prop="learntime">
                    <InputNumber :min="1" v-model="expForm.learntime" style="width: 100%" placeholder="计划学时"></InputNumber>
                  </FormItem>
                </Col>
              </Row>
            </FormItem>
            <FormItem label="项目名称" prop="title">
                <Input v-model="expForm.title" clearable placeholder="请输入实验项目名称"></Input>
            </FormItem>
            <FormItem label="耗材需求" prop="resources">
                <Input type="textarea" v-model="expForm.resources" clearable placeholder="本次实验的耗材需求"></Input>
            </FormItem>
            <FormItem label="系统需求" prop="system">
                <Input type="textarea" v-model="expForm.system" clearable placeholder="本次实验的系统需求"></Input>
            </FormItem>
            <FormItem label="软件需求" prop="software">
                <Input type="textarea" v-model="expForm.software" clearable placeholder="本次实验的软件需求"></Input>
            </FormItem>
            <FormItem
              label="时间及实验室"
              v-for="(timeItem, expTimeIndex) in expForm.expTimeItems"
              :key="timeItem.guid"
              class="ivu-form-item-required ivu-divider-dashed">
              <Row :gutter="20" type="flex" justify="start">
                <Col span="3" class="pl-15">时间：</Col>
                <Col span="7">
                  <FormItem
                    :prop="'expTimeItems.' + expTimeIndex + '.date'"
                    :rules="ruleValidate.date">
                    <DatePicker
                      :value="timeItem.date"
                      format="yyyy-MM-dd"
                      type="daterange"
                      confirm
                      clearable
                      :enabledPreventOverflow="enabledPreventOverflow"
                      placeholder="请选择实验时间"
                      @on-change="changeExpDate(timeItem, $event)"
                      style="width: 100%;"></DatePicker>
                  </FormItem>
                </Col>
                <Col span="14" class="pl-15">
                  <span class="mr-10">周末是否上课：</span>
                  <i-switch v-model="timeItem.haveClassOnWeekend" size="small" @on-change="onChangeHaveClassSwitch(timeItem)" :disabled="isWeekend(timeItem.date)">
                  </i-switch>
                  <span style="color: #b9b9b9;margin-left: 10px;">{{ timeItem.haveClassOnWeekend ? isWeekend(timeItem.date) ? '当前所选时间为周末，此处必选为上课' : '( 上课 )' : '( 不上课 )'}}</span>
                </Col>
              </Row>
              <br>
              <Row :gutter="20" type="flex" justify="space-between">
                <Col span="3" class="pl-15 pr-0">学院：</Col>
                <Col span="12">
                  <FormItem :prop="'expTimeItems.' + expTimeIndex + '.institute'"
                          :rules="ruleValidate.institute">
                    <Select v-model="timeItem.institute"
                            :enabledPreventOverflow="enabledPreventOverflow"
                            placeholder="请选择实验室所属学院"
                            filterable
                            :not-found-text="loading.institute ? '查询学院中，请稍等...' : '无可选学院'"
                            @on-change="changeExpDate(timeItem, $event)">
                      <Option v-for="(option, index) in options.institute" :value="option" :key="index">{{ option }}</Option>
                    </Select>
                  </FormItem>
                </Col>
                <Col span="8" offset="1"></Col>
              </Row>
              <br>
              <Row :gutter="20" type="flex" justify="space-between">
                <Col span="3" class="pl-15 pr-0">实验室：</Col>
                <Col span="12">
                  <FormItem
                    :prop="'expTimeItems.' + expTimeIndex + '.classroom'"
                    :rules="ruleValidate.classroom">
                    <Select
                      v-model="timeItem.classroom"
                      :loading="timeItem.labLoading"
                      :enabledPreventOverflow="enabledPreventOverflow"
                      :disabled="!(timeItem.institute && timeItem.date.length > 0 && timeItem.date[0] !== '' && timeItem.date[1] !== '')"
                      :placeholder="timeItem.institute ? (timeItem.date.length > 0 && timeItem.date[0] !== '' && timeItem.date[1] !== '' ? '请选择实验室' : '请先选择实验时间') : '请先选择学院'"
                      loading-text="查询实验室中，请稍等"
                      multiple>
                      <Option
                        v-for="item in timeItem.labList"
                        :label="item.code"
                        :value="item.code"
                        :key="item.code"
                        :disabled="!('ACTIVATING'===item.status)">
                        <span>{{ item.code }}</span>
                        <span style="float:right;color:#ccc;margin-right: 15px;">{{ item.name + ' (' + item.capacity + '人)' }}</span>
                      </Option>
                    </Select>
                  </FormItem>
                </Col>
                <Col span="8" offset="1" class="text-right">
                  <Poptip
                    confirm
                    title="确认删除该实验时间吗？"
                    @on-ok="removeTime(timeItem, expTimeIndex)"
                    v-if="!(expTimeIndex === 0 && expForm.expTimeItems.length === 1)"
                    :options="popperOpts"
                    class="text-left">
                    <Tooltip content="删除该实验时间">
                      <Button type="warning" shape="circle" icon="md-trash"></Button>
                    </Tooltip>
                  </Poptip>
                  <Tooltip content="新增实验时间"
                            v-if="expTimeIndex + 1 === expForm.expTimeItems.length"
                            style="margin-left: 1.5em">
                    <Button type="info" shape="circle" icon="md-add"
                            @click="addTime()"></Button>
                  </Tooltip>
                </Col>
              </Row>
            </FormItem>
          </fieldset>
      </Form>
      <div id="actions" class="text-center position-relative">
        <Poptip
            confirm
            :title="editSingle ? '确定修改该子实验吗？' : '确认新增该子实验吗？'"
            word-wrap
            width="180"
            @on-ok="handleSave"
            class="text-left"
            :options="popperOpts">
            <Button type="success" :loading="loading.submit" class="mr-20">
              <span v-if="!loading.submit">提交表单</span>
              <span v-else>提交中...</span>
            </Button>
        </Poptip>
        <Poptip
            confirm
            title="数据将不可恢复，确定重置表单吗？"
            word-wrap
            width="180"
            @on-ok="handleReset"
            class="text-left"
            :options="popperOpts">
          <Button style="margin-left: 8px" :disabled="loading.submit">重置表单</Button>
        </Poptip>
      </div>
    </div>
    <div class="modal-container">
      <Modal v-model="modal.show" width="550" @on-ok="modal.show = false">
        <p slot="header" class="text-center" style="color:#f60;">
          <Icon type="ios-information-circle"></Icon>
          <span>{{ modal.title }}</span>
        </p>
        <div>
          <Table height="300" border size="small" :columns="occupyColumns" :data="occupyData"></Table>
        </div>
      </Modal>
    </div>
  </div>
</template>
<script>
import { getInstituteList, getLabByDates, getLabByInstitute, addTrainingSingleExp, updateTrainingSingleExp, getFormDetailByCode } from '@/api/apply-form'
import { generateGuid } from '@/libs/tools'
export default {
  name: 'SaveTrainingExp',
  data () {
    const validateExpDate = (rule, value, callback) => {
      if (value && value[0] && value[1]) {
        callback()
      } else {
        callback(new Error('请选择实验时间'))
      }
    }
    return {
      loading: {
        institute: false,
        submit: false
      },
      options: {
        institute: []
      },
      expForm: {
        app_code: null,
        sid: 1,
        type: null,
        title: null,
        learntime: null,
        resources: null,
        system: null,
        software: null,
        expTimeItems: [
          {
            guid: generateGuid(),
            institute: '',
            date: ['', ''],
            haveClassOnWeekend: false,
            classroom: [],
            labList: [],
            labLoading: false
          }
        ]
      },
      ruleValidate: {
        institute: [
          {required: true, message: '学院不能为空', trigger: 'change'}
        ],
        classroom: [
          {required: true, type: 'array', message: '实验室不能为空', trigger: 'change'}
        ],
        type: [
          {required: true, message: '实验类型不能为空', trigger: 'change'}
        ],
        title: [
          {required: true, message: '项目名称不能为空', trigger: 'blur'}
        ],
        date: [
          { validator: validateExpDate, trigger: 'change' }
        ],
        learntime: [
          {required: true, type: 'number', message: '学时不能为空', trigger: 'change'},
          {required: true, type: 'number', message: '学时不能为空', trigger: 'blur'}
        ],
        resources: [
          {required: true, message: '耗材需求不能为空', trigger: 'blur'}
        ],
        system: [
          {required: true, message: '系统需求不能为空', trigger: 'blur'}
        ],
        software: [
          {required: true, message: '软件需求不能为空', trigger: 'blur'}
        ]
      },
      // 原子实验项目数据
      oriData: null,
      timer: null,
      isFilledForming: false,
      isFilledFormByData: false,
      labelPosition: 'left',
      labelWidth: 100,
      // Select选择器和DatePicker日期选择器的下拉列表是否吸附，默认为true，吸附
      enabledPreventOverflow: false,
      popperOpts: {
        modifiers: {
          preventOverflow: {
            // 边界元素: scrollParent, window, viewport or any DOM element. 默认iview默认window
            boundariesElement: 'scrollParent'
          }
        }
      },
      datePickerOpts: {
        disabledDate (date) {
          return date && date.valueOf() < Date.now() - 86400000
        }
      },
      occupyColumns: [
        {
          title: '日期',
          key: 'date',
          sortable: true,
          width: 130
        },
        {
          title: '实验室',
          key: 'code'
        }
      ],
      occupyData: [],
      modal: {
        show: false,
        title: '抱歉，提交失败，实验室使用时间冲突'
      }
    }
  },
  props: {
    fieldsetTitle: {
      type: String,
      default: '实验基本信息'
    },
    app_code: {
      type: String,
      default: null
    },
    sid: {
      type: String,
      default: null
    },
    expIndex: {
      type: Number,
      default: 1
    },
    editSingle: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    // 获取学院列表
    async getInstituteOptions () {
      this.loading.institute = true
      let options = []
      try {
        let res = await getInstituteList()
        res = res.data
        if (res.code && res.data.length > 0) {
          options = res.data
        } else {
          this.$Notice.error({
            title: res.code ? '暂无学院' : '获取学院列表失败',
            desc: res.code ? '暂无可选学院，请刷新后重试' : res.info
          })
          options = []
        }
      } catch (error) {
        console.log(error)
        this.$Notice.error({
          title: '获取学院列表失败',
          desc: error
        })
        options = []
      }
      this.loading.institute = false
      return options
    },
    // 获取实验室列表
    async getLabOptionsByTime (isByTime, requestInstitute, timeItem) {
      let requestTime = {
        date: timeItem.date,
        haveClassOnWeekend: timeItem.haveClassOnWeekend
      }
      let options = []
      try {
        let res = isByTime ? await getLabByDates(requestInstitute, this.editSingle ? this.app_code : '', requestTime) : await getLabByInstitute(requestInstitute)
        res = res.data
        if (res.code && res.data.length > 0) {
          options = res.data
        } else {
          this.$Notice.error({
            title: res.code ? '暂无实验室' : '获取实验室列表失败',
            desc: res.code ? '暂无可选实验室，请刷新后重试' : res.info
          })
          options = []
        }
      } catch (error) {
        console.log(error)
        this.$Notice.error({
          title: '获取实验室列表失败',
          desc: error
        })
        options = []
      }
      return options
    },
    // 新增实验时间
    addTime () {
      this.expForm.expTimeItems.push({
        guid: generateGuid(),
        institute: this.expForm.expTimeItems[0].institute,
        date: ['', ''],
        haveClassOnWeekend: false,
        classroom: [],
        labList: [],
        labLoading: false
      })
    },
    // 删除实验时间
    removeTime (item, index) {
      if (this.expForm.expTimeItems.indexOf(item) !== -1) {
        this.expForm.expTimeItems.splice(index, 1)
      }
    },
    // 改变实训项目时间回调函数
    async changeExpDate (item, value) {
      if (this.getElClass(value) === 'Array') {
        item.date = value
        if (this.isWeekend(value)) {
          item.haveClassOnWeekend = true
        }
      }
      let institute = item.institute
      if (institute && item.date.length > 0 && item.date[0] !== '' && item.date[1] !== '') {
        try {
          item.labLoading = true
          item.labList = []
          item.labList = await this.getLabOptionsByTime(true, institute, item)
          item.classroom = []
          item.labLoading = false
        } catch (error) {
          console.log(error)
          item.labList = []
        }
      }
    },
    // 改变周日是否上课
    async onChangeHaveClassSwitch (item) {
      let institute = item.institute
      if (institute && item.date.length > 0 && item.date[0] !== '' && item.date[1] !== '') {
        try {
          item.labLoading = true
          item.labList = []
          item.labList = await this.getLabOptionsByTime(true, institute, item)
          item.classroom = []
          item.labLoading = false
        } catch (error) {
          item.labList = []
        }
      }
    },
    // 通过appCode获取历史申请表的详细信息
    async getPastFormByCode (code) {
      try {
        let res = await getFormDetailByCode(code)
        res = res.data
        if (res.code) {
          let formData = res.data
          try {
            this.fillFormByData(formData)
          } catch (error) {
            this.$emit('failFillFrom', '抱歉，获取登记表信息失败，请刷新后重试。' + error)
          }
        } else {
          this.$emit('failFillFrom', '抱歉，获取登记表信息失败，请刷新后重试。' + res.info)
        }
      } catch (error) {
        this.$emit('failFillFrom', '抱歉，获取登记表信息失败，请刷新后重试。' + error)
        console.log(error)
      }
    },
    // 通过从后台获取的数据填充到当前表单中
    async fillFormByData (data) {
      this.isFilledForming = true
      let expItem = null
      this.expForm.app_code = data.appCode
      // 处理实验子项目数据
      for (let i = 0; i < data.expBaseInfoItems.length; i++) {
        const item = data.expBaseInfoItems[i]
        item.guid = generateGuid()
        item.learntime = item.plan_hours
        item.expTimeItems = item.expTimeItemsTrain
        delete item.plan_hours
        delete item.actual_hours
        delete item.expTimeItemsCourse
        delete item.expTimeItemsTrain
        // 处理子实验的数据
        for (let j = 0; j < item.expTimeItems.length; j++) {
          const time = item.expTimeItems[j]
          time.guid = generateGuid()
          time.date = time.dates
          time.institute = time.classroom[0].institute
          time.labList = []
          if (item.sid === this.sid) {
            time.labLoading = true
            // 获取 子实验 下的 子实验时间 的实验室列表
            try {
              time.labList = await this.getLabOptionsByTime(true, time.institute, time)
            } catch (error) {
              console.log(error)
              this.$Notice.error({
                title: '获取可选实验室列表失败',
                desc: error
              })
              time.labLoading = false
              time.labList = []
            }
            time.classroom = time.classroom.map(item => {
              return item.code
            })
            time.labLoading = false
            delete time.labCodes
            delete time.dates
          }
        }
        if (item.sid === this.sid) {
          expItem = item
        }
      }
      if (expItem) {
        this.$nextTick(() => {
          this.oriData = JSON.parse(JSON.stringify(expItem))
          this.expForm = expItem
          setTimeout(() => {
            this.isFilledFormByData = true
          }, 1000)
          this.$Spin.hide()
        })
      } else {
        this.$Notice.error({
          title: '获取子实验失败',
          desc: '抱歉，该子实验已经不存在，请刷新后重试'
        })
      }
    },
    // 保存 新增/修改的单个实验
    handleSave () {
      this.$refs['expForm'].validate(async (valid) => {
        if (valid) {
          this.loading.submit = true
          console.log(valid)
          this.showSpinWithTip('提交表单中，请稍等...')
          try {
            let data = JSON.parse(JSON.stringify(this.expForm, function (key, value) {
              if (key === 'labList' || key === 'labLoading' || key === 'guid') {
                return undefined
              } else {
                return value
              }
            }))
            data.app_code = this.app_code
            data.sid = this.sid
            let response = this.editSingle ? await updateTrainingSingleExp(JSON.stringify(data)) : await addTrainingSingleExp(JSON.stringify(data))
            let res = response.data
            if (res.code) {
              this.$emit('saveSuccess', this.editSingle)
            } else {
              if (this.getElClass(res.data) === 'Array' && res.data.length > 0) {
                this.occupyData = []
                for (let i = 0; i < res.data.length; i++) {
                  for (let key in res.data[i]) {
                    if (res.data[i].hasOwnProperty(key)) {
                      let item = {
                        date: key,
                        code: res.data[i][key].join('、')
                      }
                      this.occupyData.push(item)
                    }
                  }
                }
                this.modal = {
                  'show': true,
                  'title': res.info ? res.info : '抱歉，实验室使用时间冲突，请重新选择'
                }
              } else {
                this.$Notice.error({
                  title: '提交失败',
                  desc: (this.editSingle ? '修改单个实验信息失败，' : '新增单个实验失败，') + res.info
                })
              }
            }
          } catch (error) {
            console.log(error)
            this.$Notice.error({
              title: '提交失败',
              desc: (this.editSingle ? '修改单个实验信息失败，' : '新增单个实验失败，') + error
            })
          }
          this.$Spin.hide()
        } else {
          this.$Notice.error({
            title: '提交失败',
            desc: '抱歉，无法提交，请先完善表单信息再提交。'
          })
        }
      })
      this.loading.submit = false
    },
    // 重置表单
    handleReset () {
      this.$refs['expForm'].resetFields()
      this.resetFormData()
    },
    resetFormData () {
      let notData = {
        sid: 1,
        type: null,
        title: null,
        learntime: null,
        resources: null,
        system: null,
        software: null,
        expTimeItems: [
          {
            guid: generateGuid(),
            institute: '',
            date: ['', ''],
            haveClassOnWeekend: false,
            classroom: [],
            labList: [],
            labLoading: false
          }
        ]
      }
      this.expForm = JSON.parse(JSON.stringify(this.editSingle ? this.oriData : notData))
    },
    // 显示带文字提示的Spin
    showSpinWithTip (tip) {
      this.$Spin.show({
        render: h => {
          return h('div', { class: 'ivu-spin-large' }, [
            h('span', {
              class: 'ivu-spin-dot',
              style: {
                display: 'inline-block'
              }
            }),
            h('div', tip)
          ])
        }
      })
    },
    getElClass (o) {
      if (o === null) return 'Null'
      if (o === undefined) return 'undefined'
      return Object.prototype.toString.call(o).slice(8, -1)
    },
    isWeekend (date) {
      let start = new Date(date[0])
      let end = new Date(date[1])
      // 前后日相差期是否小于两天
      let differ = Date.parse(end) - Date.parse(start)
      let isLessOrEqualTwoDay = differ <= 86400000
      // 获取星期几，0 ~ 6 分别对应 周日到周六
      let week = {
        start: start.getDay(),
        end: end.getDay()
      }
      // 判断是不是 同一天周六/周日，或者是周六周日两天
      let isSatOrSun = ((week.start === 6 && week.end === 6) || (week.start === 0 && week.end === 0) || (week.start === 6 && week.end === 0))
      return isSatOrSun && isLessOrEqualTwoDay
    }
  },
  created: async function () {
    this.options.institute = await this.getInstituteOptions()
  },
  mounted: function () {
    // 全局配置Notice组件的属性
    this.$Notice.config({
      top: window.innerHeight / 3
    })
    if (this.editSingle) {
      this.showSpinWithTip('加载历史数据中...')
      this.getPastFormByCode(this.app_code)
    }
  },
  beforeDestroy () {
    this.$Notice.destroy()
    this.$Modal.remove()
  }
}
</script>
<style lang="less" scoped>
  .form-container {
    .ivu-divider-dashed {
      border-color: #ccc;
      padding-top: 20px;
    }
  }
</style>
